package cs561.hao;
//java GamePlaying -d 4 6 -e 1 2 -i racetrack1.txt
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Vector;

public class GamePlaying {
	
	//public int[][] leastG;

	public int[][]readFile(String file)
	{
		int width = 0;
		int height = 0;
		int[][]points = null;
		int pointType = -1;
		
		try {
			FileReader fr = new FileReader(file);
			BufferedReader br = new BufferedReader(fr);	
			int lineNum = 0;
		
			try {
				while((br.ready()) && (lineNum < 2))
				{					
					String line = br.readLine();
					if (lineNum == 0)
					{
						String[] str = line.split(" ");
						width = Integer.parseInt(str[1]);
					}
					else if (lineNum == 1)
					{
						String[] str = line.split(" ");
						height = Integer.parseInt(str[1]);
					}
					lineNum++;
				}				
				
				points = new int[height][width];
				//leastG = new int[height][width];
				
				//while(width/factor>0)
					//factor = factor * 10;
				
				for(int i = 0; i < height; i++)
				{
					for(int j = 0; j < width; j++)
					{
						if(br.ready())
						{
							pointType = br.read();
							//System.out.println("pointType: " + pointType);
							switch(pointType) 
							{
								case 35: points[i][j] = -1;//#  off road
										 break;
								case 32: points[i][j] = 1;//' ' road
										 break;
								case 83: points[i][j] = 2;//S   start
										 break;
								case 65: points[i][j] = 3;//A   alter start
										 break;
								case 70: points[i][j] = 4;//F	finish
										 break;
								default: System.out.println("Invalid input.");
										 System.exit(-1);
										 break;
							}
							//System.out.println("Read i = " + i + ", j = " + j + ", " + points[i][j]);
						}
					}
					br.skip(1);//the last character of the line is \n, so skip
				}	
				
			} catch (IOException e) {
				e.printStackTrace();
			}
		
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}	
		
		return points;
	}//end readFile
	
	public void writePoints(int width, int height, int points[][])
	{
		
		try {
			FileWriter fw = new FileWriter("./src/cs561/hao/cs561_project2_yujie's_game_points_output.txt");
			BufferedWriter bw = new BufferedWriter(fw);
			for(int i = 0; i < height; i++)
			{
				for(int j = 0; j < width; j++)
				{
					//System.out.println("Write i = " + i + ", j = " + j + ", " + points[i][j]);
					switch(points[i][j])
					{
						case -1:bw.write('#');
								break;
						case  1:bw.write(' ');
								break;
						case  2:bw.write('S');
								break;
						case  3:bw.write('A');
								break;
						case  4:bw.write('F');
								break;
					}
					
				}
				bw.newLine();
			}
			bw.flush();
			bw.close();
			
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}//end writePoints	
	
	public static Vector<int[]> breakTheMovementVector(int i,int j)//A/B//!
	{
		Vector<int[]> result=new Vector<int[]>();
		int signOfI;
		int signOfJ;
		double ii=new Double(Math.abs(i));
		double jj=new Double(Math.abs(j));
		if(i==0 && j==0)
			return result;
		if(i>0) signOfI=1; else signOfI=-1;
		if(j>0) signOfJ=1; else signOfJ=-1;
		if (j==0){
			for (int f=0;f<ii;f++){
				int[] point={signOfI,0};
				result.add(point);
			}
			return result;
		}
		if (i==0){
			for (int f=0;f<jj;f++){
				int[] point={0,signOfJ};
				result.add(point);
			}
			return result;
		}
		Double a=1.0;
		Double b=1.0;
		double cross=((ii/jj)*(a-.5)+.5);
		while (b<=ii || a<=jj){
			if (b>cross){
				int[] point={0,signOfJ};
				result.add(point);
				a++;
				cross=((ii/jj)*(a-.5)+.5);
			}
			else if (b==cross){
				int[] point={signOfI,signOfJ};
				result.add(point);
				a++;
				b++;
				cross=((ii/jj)*(a-.5)+.5);
			}
			else if (b<cross){
				int[] point={signOfI,0};
				result.add(point);
				b++;
			}
		}
			return result;
	}//end breakTheMovementVector
	
	public static void main(String[] args)
	{
		//java GamePlaying -d 4 6 -e 1 2 -i racetrack1.txt
		int player_1_depth = Integer.parseInt(args[1]);
		int player_2_depth = Integer.parseInt(args[2]);
		int player_1_evl = Integer.parseInt(args[4]);
		int player_2_evl = Integer.parseInt(args[5]);
        String myInputFile = args[7];
		String myOutputFile = "./src/cs561/hao/cs561_project2_yujie's_game_result.txt";		
		
		//start
		SimpleDateFormat sdf = new SimpleDateFormat("MMM d, EEE, yyyy HH:mm:ss.S Z");
		String myBeginSystemTime = sdf.format(new Date()).toString();		
		Date beginTime = null;
		long beginTimeSecond = 0;
		Date endTime = null;
		long endTimeSecond = 0;	
		long searchTime = 0;
		boolean have_alt = false;
		
		try {
			beginTime = sdf.parse(myBeginSystemTime);
			beginTimeSecond = beginTime.getTime();
		} catch (ParseException e) {
			e.printStackTrace();
			System.exit(-1);
		}		
		
		GamePlaying myGame = new GamePlaying();
		int myWidth;
		int myHeight;		
		int[][]originalCells = null; // original cells.	
		//int numOfExpPoints = 0;
				
		ArrayList<int[]> startCells = new ArrayList<int[]>();//2,x,y
		ArrayList<int[]> alterStartCells = new ArrayList<int[]>(); //3, x,y
		ArrayList<int[]> roadCells = new ArrayList<int[]>(); //1,  x,y
		ArrayList<int[]> offRoadCells = new ArrayList<int[]>(); //-1, x,y
		ArrayList<int[]> finishCells = new ArrayList<int[]>(); //4,  x,y
		//ArrayList<int[]> myCurrentPointsList = new ArrayList<int[]>();//xk,yk,hk,ik-1,jk-1
		//ArrayList<int[]> myNextPointsList = new ArrayList<int[]>();//xk+1,yk+1,hk+1,ik,jk  
		int[] size2Array1 = new int[2];
				
		originalCells = myGame.readFile(myInputFile);
		myHeight = originalCells.length;
		myWidth = originalCells[0].length;		
		System.out.println("main: myWidth = " + myWidth + ", myHeight = " + myHeight);
		myGame.writePoints(myWidth, myHeight, originalCells);	
		
		try{
			FileWriter myFileWriter = new FileWriter(myOutputFile);
			BufferedWriter myBW = new BufferedWriter(myFileWriter);		
			//add original points to ArrayLists.
			for(int i = 0; i < myHeight; i++) // In the future, I should write this part as a method, use each array as a formal parameter;
			{
				for(int j = 0; j < myWidth; j++)
				{
					switch(originalCells[i][j])
					{
						case -1: 
							size2Array1 = new int[2];
							size2Array1[0] = j;
							size2Array1[1] = i;
							//System.out.println("offRoad i = " + i + ", j = " + j);
							offRoadCells.add(size2Array1);
							break;
						case  1:						
							//size3Array[0] = i;
							//size3Array[1] = j;
							//size3Array[2] = -1;
							size2Array1 = new int[2];
							size2Array1[0] = j;
							size2Array1[1] = i;
							roadCells.add(size2Array1);						
							//System.out.println("roadCell i = " + i + ", j = " + j);
							break;
						case  2:
							size2Array1 = new int[2];
							size2Array1[0] = j;
							size2Array1[1] = i;
							//System.out.println("startPoint i = " + i + ", j = " + j);
							startCells.add(size2Array1);
							break;
						case  3:
							size2Array1 = new int[2];
							size2Array1[0] = j;
							size2Array1[1] = i;
							alterStartCells.add(size2Array1);
							//System.out.println("alterStartCells i = " + i + ", j = " + j);
							break;
						case  4:
							size2Array1 = new int[2];
							size2Array1[0] = j;
							size2Array1[1] = i;
							finishCells.add(size2Array1);
							//System.out.println("finishCells i = " + i + ", j = " + j);
							break;
						default:
							break;
						
					}
				}
			}
			
			if((startCells.size() != 2))
			{
				System.out.println("Error! There must be 2 start cells!");
				System.exit(-1);
			}
			
			if(roadCells.size() == 0)
			{
				System.out.println("Error! There is no road cell!");
				System.exit(-2);
			}
			
			if(finishCells.size() == 0)
			{
				System.out.println("Error! There is no finish cell!");
				System.exit(-3);
			}
			
			boolean myFinishRun = false;
			System.out.println("S1: " + startCells.get(0)[0] + ", " + startCells.get(0)[1]);
			System.out.println("S2: " + startCells.get(1)[0] + ", " + startCells.get(1)[1]);
			// create root node.
			
			
			
			//:
			//change
			
			//int myDepth = 2;
			//int myDepth = 4;
			//int myDepth = 6;
			//int myDepth = 8;
			
			
			
			
			
			
			System.out.println("main: player1 depth = " + player_1_depth);
			System.out.println("main: player2 depth = " + player_2_depth);
			TreeNode myRootNode1 = new TreeNode();
			myRootNode1.alpha = Integer.MIN_VALUE;
			myRootNode1.beta = Integer.MAX_VALUE;
			myRootNode1.nodeName = "root1";
			myRootNode1.p1.x_current = startCells.get(0)[0];
			myRootNode1.p1.y_current = startCells.get(0)[1];
			TreeNode emptyNode1 = new TreeNode();
			myRootNode1.parent = emptyNode1;
			
			System.out.println(" -- ");
			System.out.println();
			System.out.println("1. Try to start from startcell 1.");
			Alpha_beta_pruning.expand_num = 0;
			//System.out.println("Player 1 start at p1.x = " + myRootNode1.p1.x_current);
			//System.out.println("Player 1 start at p1.y = " + myRootNode1.p1.y_current);
			myRootNode1.p1.i_last = 0;
			myRootNode1.p1.j_last = 0;
			
			myRootNode1.p2.x_current = startCells.get(1)[0];
			myRootNode1.p2.y_current = startCells.get(1)[1];
			//System.out.println("Player 2 start at p2.x = " + myRootNode1.p2.x_current);
			//System.out.println("Player 2 start at p2.y = " + myRootNode1.p2.y_current);			
			myRootNode1.p2.i_last = 0;
			myRootNode1.p2.j_last = 0;
			myRootNode1.utility = Alpha_beta_pruning.evaluation(myRootNode1, finishCells,player_1_evl);
			
			System.out.println();			
			System.out.println(myRootNode1.nodeName + ".p1: (x,y,i_last,j_last,minD,uti) = (" + myRootNode1.p1.x_current + "," 
					+ myRootNode1.p1.y_current + "," + myRootNode1.p1.i_last + "," + 
					myRootNode1.p1.j_last + "," + myRootNode1.p1.minDistance + "," + myRootNode1.utility +")");			
			System.out.println(myRootNode1.nodeName + ".p2: (x,y,i_last,j_last,minD,uti) = (" + myRootNode1.p2.x_current + "," 
					+ myRootNode1.p2.y_current + "," + myRootNode1.p2.i_last + "," + 
					myRootNode1.p2.j_last + "," + myRootNode1.p2.minDistance + "," + myRootNode1.utility +")");
			
			TreeNode resultNode1 = Alpha_beta_pruning.abp(myRootNode1, player_1_depth, -1, originalCells, finishCells, player_1_evl, player_2_evl);
			
			System.out.println(" \n * * * \n ");
			System.out.println();
			System.out.println("2. Try to start from startcell 2.");
			Alpha_beta_pruning.expand_num = 0;
			TreeNode myRootNode2 = new TreeNode();
			myRootNode2.alpha = Integer.MIN_VALUE;
			myRootNode2.beta = Integer.MAX_VALUE;
			myRootNode2.nodeName = "root2";
			TreeNode emptyNode2 = new TreeNode();
			myRootNode2.parent = emptyNode2;
			myRootNode2.p1.x_current = startCells.get(1)[0];
			myRootNode2.p1.y_current = startCells.get(1)[1];
			//System.out.println("Player 1 start at p1.x = " + myRootNode2.p1.x_current);
			//System.out.println("Player 1 start at p1.y = " + myRootNode2.p1.y_current);
			myRootNode2.p1.i_last = 0;
			myRootNode2.p1.j_last = 0;
			
			myRootNode2.p2.x_current = startCells.get(0)[0];
			myRootNode2.p2.y_current = startCells.get(0)[1];
			//System.out.println("Player 2 start at p2.x = " + myRootNode2.p2.x_current);
			//System.out.println("Player 2 start at p2.y = " + myRootNode2.p2.y_current);						
			myRootNode2.p2.i_last = 0;
			myRootNode2.p2.j_last = 0;
			myRootNode2.utility = Alpha_beta_pruning.evaluation(myRootNode2, finishCells,player_1_evl);
			
			System.out.println();			
			System.out.println(myRootNode2.nodeName + ".p1: (x,y,i_last,j_last,minD,uti) = (" + myRootNode2.p1.x_current + "," 
					+ myRootNode2.p1.y_current + "," + myRootNode2.p1.i_last + "," + 
					myRootNode2.p1.j_last + "," + myRootNode2.p1.minDistance + "," + myRootNode2.utility +")");			
			System.out.println(myRootNode2.nodeName + ".p2: (x,y,i_last,j_last,minD,uti) = (" + myRootNode2.p2.x_current + "," 
					+ myRootNode2.p2.y_current + "," + myRootNode2.p2.i_last + "," + 
					myRootNode2.p2.j_last + "," + myRootNode2.p2.minDistance + "," + myRootNode2.utility +")");
			
			TreeNode resultNode2 = Alpha_beta_pruning.abp(myRootNode2, player_1_depth, -1, originalCells, finishCells,player_1_evl,player_2_evl);
			
			System.out.println();
			System.out.println("\n\n\n---- Root1 and Root 2 startcell results: -----\n\n\n");			
			
			System.out.println("Root 1 final result: " + resultNode1.nodeName);			
			System.out.println(resultNode1.nodeName + ".p1: (x,y,i_last,j_last,minD,uti) = (" + resultNode1.p1.x_current + "," 
					+ resultNode1.p1.y_current + "," + resultNode1.p1.i_last + "," + 
					resultNode1.p1.j_last + "," + resultNode1.p1.minDistance + "," + resultNode1.utility +")");				
			System.out.println(resultNode1.nodeName + ".p2: (x,y,i_last,j_last,minD,uti) = (" + resultNode1.p2.x_current + "," 
					+ resultNode1.p2.y_current + "," + resultNode1.p2.i_last + "," + 
					resultNode1.p2.j_last + "," + resultNode1.p2.minDistance + "," + resultNode1.utility +")");			
			
			System.out.println();			
			System.out.println("Root 2 final result: " + resultNode2.nodeName);
			System.out.println(resultNode2.nodeName + ".p1: (x,y,i_last,j_last,minD,uti) = (" + resultNode2.p1.x_current + "," 
					+ resultNode2.p1.y_current + "," + resultNode2.p1.i_last + "," + 
					resultNode2.p1.j_last + "," + resultNode2.p1.minDistance + "," + resultNode2.utility +")");				
			System.out.println(resultNode2.nodeName + ".p2: (x,y,i_last,j_last,minD,uti) = (" + resultNode2.p2.x_current + "," 
					+ resultNode2.p2.y_current + "," + resultNode2.p2.i_last + "," + 
					resultNode2.p2.j_last + "," + resultNode2.p2.minDistance + "," + resultNode2.utility +")");
						
			TreeNode startRoot = null;
			
			System.out.println();
			if(resultNode1.utility > resultNode2.utility)
			{
				startRoot = myRootNode1;
				startRoot.root = true;
				System.out.println("Player 1 choose S1, p1 start from (x,y) = (" + startRoot.p1.x_current + "," + startRoot.p1.y_current + ").");
				System.out.println("                    p2 start from (x,y) = (" + startRoot.p2.x_current + "," + startRoot.p2.y_current + ").");
			}
			else
			{
				startRoot = myRootNode2;
				startRoot.root = true;
				System.out.println("Player 1 choose S2, p1 start from (x,y) = (" + startRoot.p1.x_current + "," + startRoot.p1.y_current + ").");
				System.out.println("                    p2 start from (x,y) = (" + startRoot.p2.x_current + "," + startRoot.p2.y_current + ").");
			}
			
			startRoot.utility = Alpha_beta_pruning.evaluation(startRoot, finishCells,player_2_evl);
			
			TreeNode resultNodeP1 = null;
			TreeNode resultNodeP2 = null;
			//TreeNode nextStepP1 = startRoot;
			TreeNode nextStepP1 = new TreeNode();
			TreeNode nextStepP2 = new TreeNode();
			TreeNode myParentNode = null;
			System.out.println("\n\n\n ###########################################\n\n\nNow begin to compete!\n\n ");
			
			Alpha_beta_pruning.expand_num = 0;
			TreeNode emptyHead = new TreeNode();
			nextStepP1.parent = emptyHead;			
			nextStepP1.alpha = Integer.MIN_VALUE;
			nextStepP1.beta = Integer.MAX_VALUE;
			nextStepP1.p1 = startRoot.p1;
			nextStepP1.p2 = startRoot.p2;	
			nextStepP1.nodeName = "nextStepP1";
			nextStepP2.nodeName = "nextStepP2";
			nextStepP1.utility = Alpha_beta_pruning.evaluation(nextStepP1, finishCells,player_2_evl);
			
			
			while(myFinishRun == false)//core			
			//for(int i = 0; i < 1; i++)
			{
				
				//player 2 go.
				System.out.println(" \n\np2: < -- player 2 start \n\n");				
				resultNodeP2 = Alpha_beta_pruning.abp(nextStepP1, player_2_depth, -1, originalCells, finishCells,player_1_evl,player_2_evl);			
				//find sub root.
				myParentNode = resultNodeP2;
				
				if(resultNodeP2.root == true) nextStepP2 = resultNodeP2;				
								
				else if(resultNodeP2.parent.root == true)
				{
					nextStepP2 = resultNodeP2;
				}
				
				else if(resultNodeP2.parent.parent.root == true)
				{
					nextStepP2 = resultNodeP2.parent;
				}
				
				else
				{
					while(myParentNode.parent.parent.root != true)
					{
						myParentNode = myParentNode.parent;
					}
					nextStepP2 = myParentNode.parent;
				}
				
				TreeNode emptyHead2 = new TreeNode();
				System.out.println("p2 before move: \np1: (x,y,i,j,d) = (" + nextStepP1.p1.x_current + "," + nextStepP1.p1.y_current + "," + nextStepP1.p1.i_last + "," + nextStepP1.p1.j_last + "," + nextStepP1.p1.minDistance + ")");				
				System.out.println("p2: (x,y,i,j,d) = (" + nextStepP1.p2.x_current + "," + nextStepP1.p2.y_current + "," + nextStepP1.p2.i_last + "," + nextStepP1.p2.j_last + "," + nextStepP1.p2.minDistance + ")");
				
				nextStepP2.parent = emptyHead2;
				nextStepP2.root = true;// ! core! make this result as a root node for opponent!
				nextStepP2.alpha = Integer.MIN_VALUE;
				nextStepP2.beta = Integer.MAX_VALUE;
				nextStepP2.p1 = nextStepP1.p1;//not change!
				//nextStepP2.p2 = nextStepP2.p2;
				nextStepP2.utility = Alpha_beta_pruning.evaluation(nextStepP2, finishCells,player_1_evl);
				//nextStepP2.nodeName = "nextStepP2";
				
				System.out.println("p2 after move: ");
				System.out.println("p2 go to node: " + nextStepP2.nodeName);
				System.out.println("p1:(x,y,i_last,j_last,minD,uti) = (" + nextStepP2.p1.x_current + ", " + nextStepP2.p1.y_current + ", " + nextStepP2.p1.i_last + ", " + nextStepP2.p1.j_last + ", " + nextStepP2.p1.minDistance + "," + nextStepP2.utility +")" );
				System.out.println("p2:(x,y,i_last,j_last,minD,uti) = (" + nextStepP2.p2.x_current + ", " + nextStepP2.p2.y_current + ", " + nextStepP2.p2.i_last + ", " + nextStepP2.p2.j_last + ", " + nextStepP2.p2.minDistance + "," + nextStepP2.utility +")" );
				
				if(nextStepP2.p2.minDistance == 0)
				{
					System.out.println("\n\np2: player 2 win! He arrives at finish line!!!\n\n");
					System.out.println(" \n\np2: player 2 stop -- >\n\n");
					break;
				}
				
				
				
				System.out.println(" \n\np2: player 2 stop -- >\n\n");	
				////////////////////////////////////////////
				
				//player 1 go.
				System.out.println("\n\np1: < -- player 1 start \n\n");
				resultNodeP1 = Alpha_beta_pruning.abp(nextStepP2, player_1_depth, 1, originalCells, finishCells,player_1_evl, player_2_evl);
				//find sub root.
				myParentNode = resultNodeP1;
				
				if(resultNodeP1.root == true) nextStepP1 = resultNodeP1;
				
				else if(resultNodeP1.parent.root == true)
				{
					nextStepP1 = resultNodeP1;
				}
				
				else if(resultNodeP1.parent.parent.root == true)
				{
					nextStepP1 = resultNodeP1.parent;
				}
				
				else
				{
					while(myParentNode.parent.parent.root != true)
					{
						myParentNode = myParentNode.parent;
					}
					nextStepP1 = myParentNode.parent;
				}	
				
				TreeNode emptyHead1 = new TreeNode();
				System.out.println("p1 before move: \np1: (x,y,i,j,d) = (" + nextStepP2.p1.x_current + "," + nextStepP2.p1.y_current + "," + nextStepP2.p1.i_last + "," + nextStepP2.p1.j_last + "," + nextStepP2.p1.minDistance + ")");				
				System.out.println("p2: (x,y,i,j,d) = (" + nextStepP2.p2.x_current + "," + nextStepP2.p2.y_current + "," + nextStepP2.p2.i_last + "," + nextStepP2.p2.j_last + "," + nextStepP2.p2.minDistance + ")");
				
				
				nextStepP1.parent = emptyHead1;
				nextStepP1.root = true;// ! core! make this result as a root node for opponent!
				nextStepP1.alpha = Integer.MIN_VALUE;
				nextStepP1.beta = Integer.MAX_VALUE;
				nextStepP1.p2 = nextStepP2.p2;//not change!
				nextStepP1.utility = Alpha_beta_pruning.evaluation(nextStepP1, finishCells,player_2_evl);
				//nextStepP1.nodeName = "nextStepP1";

				System.out.println("p1 after move: ");		
				System.out.println("p1 go to node: " + nextStepP1.nodeName);
				System.out.println("p1:(x,y,i_last,j_last,minD,uti) = (" + nextStepP1.p1.x_current + ", " + nextStepP1.p1.y_current + ", " + nextStepP1.p1.i_last + ", " + nextStepP1.p1.j_last + ", " + nextStepP1.p1.minDistance + "," + nextStepP1.utility +")" );
				System.out.println("p2:(x,y,i_last,j_last,minD,uti) = (" + nextStepP1.p2.x_current + ", " + nextStepP1.p2.y_current + ", " + nextStepP1.p2.i_last + ", " + nextStepP1.p2.j_last + ", " + nextStepP1.p2.minDistance + "," + nextStepP1.utility +")" );
				
				if(nextStepP1.p1.minDistance == 0)
				{
					System.out.println("\n\np1: player 1 win! He arrives at finish line!!!\n\n");
					System.out.println("\n\np1: player 1 stop -- >\n\n");	
					break;
				}
				System.out.println("\n\np1: player 1 stop -- >\n\n");	
				
				
				
						
				
				
			}
						

				
			
			// end time		
			String myEndSystemTime = sdf.format(new Date()).toString();
			try {
				endTime = sdf.parse(myEndSystemTime);
				endTimeSecond = endTime.getTime();
			} catch (ParseException e) {
				e.printStackTrace();
				System.exit(-1);
			}	
			
			searchTime = (endTimeSecond - beginTimeSecond)/1000;
			
			
			System.out.println("main: end!");						
			//mySearch.writeOutputFile(myPathListOfList, myBW, numOfExpPoints++, searchTime);										
			
			
			
			
			
			myBW.write("end game!");
			
			myBW.flush();
			myBW.close();
			//System.out.println("main: write to file.");
		
		} catch (IOException e) {
			System.out.println(e);
		}
		
		
		
		
		
		
		
		
		
		
	}// end main	
	
	
	
	
	
	
}
